﻿namespace PowerSong.UserInterface
    {
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Windows;
    using System.Windows.Input;
    using Items;
    using PowerSong.SongDatabase;

    /// <summary>
    /// The main PowerSong window.
    /// </summary>
    public partial class MainWindow : Window
        {

        public MainWindow()
            {
            InitializeComponent();

            // Wire up events from the global static State object
            State.DatabaseLoaded += State_DatabaseLoaded;

            // Ensure we do the initial processing after the window is shown
            this.Loaded += MainWindow_Loaded;

            }

        private void State_DatabaseLoaded(Database database, Settings settings)
            {

            // Update the window title
            this.Title = "PowerSong - " + Path.GetFileNameWithoutExtension(State.Database.FileName);

            // Create live projector if necessary
            if (State.Settings.AutoCreateProjectionWindow && State.Theatre.ProjectorCount() < 2)
                {
                State.Theatre.CreateProjector();
                }

            // Set the style of the projectors to use the default style
            State.Theatre.ChangeStyle(State.Settings.DefaultStyle);

            // Update all controls
            SongsRadioButton.IsChecked = true;
            UpdateEverything();
            CategoriesListBox.SetCheckedItems(State.Database.Categories.GetAllCategories());

            }

        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
            {

            // Create preview projector
            State.Theatre.CreateProjector(PreviewProjectorGrid);

            // Process command line arguments
            var databaseLoaded = false;
            var arguments = Environment.GetCommandLineArgs();
            if (arguments.Length == 2 && File.Exists(arguments[1]))
                {
                var fileName = arguments[1];
                var extension = Path.GetExtension(fileName).ToUpper();

                // Are we loading an existing PowerSong database via the command line?
                if (extension == ".POWERSONG")
                    {
                    databaseLoaded = State.LoadDatabase(fileName);
                    }

                }

            // Show the welcome window if a database hasn't already been loaded
            if (!databaseLoaded)
                {
                var window = new WelcomeWindow();
                databaseLoaded = window.ShowDialog() == true;
                }

            // Close if no database has been loaded
            if (!databaseLoaded) this.Close();

            }

        private void ShowNothingCommandExecute(object sender, ExecutedRoutedEventArgs e)
            {
            State.Theatre.ChangeMode(ProjectorMode.Black);
            }

        private void ShowBackgroundCommandExecute(object sender, ExecutedRoutedEventArgs e)
            {
            State.Theatre.ChangeMode(ProjectorMode.Background);
            }

        private void ShowEverythingCommandExecute(object sender, ExecutedRoutedEventArgs e)
            {
            State.Theatre.ChangeMode(ProjectorMode.Full);
            }

        private void AdvanceToNextVerseCommandExecute(object sender, ExecutedRoutedEventArgs e)
            {
            if (NextButton.IsEnabled)
                {
                var newVerseIndex = Math.Max(0, VersesListBox.SelectedVerseIndex);
                if (newVerseIndex == VersesListBox.ActiveVerseIndex) newVerseIndex = (VersesListBox.ActiveVerseIndex + 1) % VersesListBox.ActiveSong.Verses.Count;
                if (newVerseIndex != VersesListBox.ActiveVerseIndex)
                    {
                    VersesListBox.ChangeVerse(newVerseIndex);
                    }
                }
            }

        private void ProjectSongNowCommandExecute(object sender, ExecutedRoutedEventArgs e)
            {
            if (SongsListBox.SelectedItem != null)
                {
                AddSongToPlayListButton_Click(sender, e);
                ServiceListBox.SelectedIndex = ServiceListBox.Items.Count - 1;
                ActivateSongButton_Click(sender, e);
                }
            }

        private void CreateProjectorWindowCommandExecute(object sender, RoutedEventArgs e)
            {
            State.Theatre.CreateProjector();
            }

        private void AboutPowerSongMenuItem_Click(object sender, RoutedEventArgs e)
            {
            new AboutWindow().ShowDialog();
            }

        private void SendFeedbackMenuItem_Click(object sender, RoutedEventArgs e)
            {
            new FeedbackWindow().ShowDialog();
            }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
            {

            // Close the database
            if (State.Database != null) State.CloseDatabase();

            // Close the bible file
            if (State.Bible != null) State.Bible.Close();

            // Remove all projectors
            State.Theatre.RemoveAllProjectors();

            }

        private void ConfigureStylesMenuItem_Click(object sender, RoutedEventArgs e)
            {
            new EditStylesWindow().ShowDialog();
            }

        private void ChangeServiceItemOptionsButton_Click(object sender, RoutedEventArgs e)
            {

            var selectedItem = (PlayListItemModel)ServiceListBox.SelectedItem;
            var item = selectedItem.Data;
            var itemEdited = true;
            if (item is VideoServiceItem)
                {
                var video = (VideoServiceItem)item;
                itemEdited = new EditVideoWindow(video).ShowDialog() == true;
                }
            else if (item is NoticeServiceItem)
                {
                var notice = (NoticeServiceItem)item;
                itemEdited = new EditNoticeWindow(notice).ShowDialog() == true;
                }
            else if (item is BannerServiceItem)
                {
                var banner = (BannerServiceItem)item;
                itemEdited = new EditBannerWindow(banner).ShowDialog() == true;
                }
            else if (item is SongServiceItem)
                {
                var song = ((SongServiceItem)item).Song;
                itemEdited = new EditSongWindow(song).ShowDialog() == true;
                }
            else
                {
                Utilities.ShowInformationMessage("Cannot Edit", "The selected play list item cannot be edited.");
                itemEdited = false;
                }

            if (itemEdited) UpdateEverything();

            }

        private void AddSongButton_Click(object sender, RoutedEventArgs e)
            {
            var window = new EditSongWindow();
            if (window.ShowDialog() == true)
                {
                UpdateSongsList();
                UpdateCategoriesList();
                UpdateEnabledState();
                }
            }

        private void DeleteSongButton_Click(object sender, RoutedEventArgs e)
            {

            var proceed = SongsListBox.SelectedItems.Count > 1
                ? Utilities.Confirm("Delete Songs", "You have selected multiple songs." + Environment.NewLine + Environment.NewLine + "Are you really sure that you want to permanently delete the selected songs?")
                : Utilities.Confirm("Delete Song", "Are you sure you want to permanently delete the selected song?");

            // Proceed if song deletion is confirmed
            if (proceed)
                {
                foreach (Song song in SongsListBox.SelectedItems)
                    {
                    State.Database.Songs.Delete(song);
                    }
                UpdateSongsList();
                UpdateEnabledState();
                }
            }

        private void EditSongButton_Click(object sender, RoutedEventArgs e)
            {
            var selectedSong = VersesListBox.ActiveSong;
            var window = new EditSongWindow(selectedSong);
            if (window.ShowDialog() == true)
                {
                VersesListBox.ChangeSong(selectedSong);
                UpdateSongsList();
                UpdateCategoriesList();
                UpdateEnabledState();
                }
            }

        private void ConfigureCategoriesMenuItem_Click(object sender, RoutedEventArgs e)
            {
            var window = new EditCategoriesWindow();
            if (window.ShowDialog() == true)
                {
                UpdateSongsList();
                UpdateCategoriesList();
                }
            }

        private void ConfigurePowerSongMenuItem_Click(object sender, RoutedEventArgs e)
            {
            var window = new ConfigurePowerSongWindow();
            if (window.ShowDialog() == true)
                {
                UpdateEverything();
                }
            }

        private void ExportDataMenuItem_Click(object sender, RoutedEventArgs e)
            {
            var window = new ExportWindow();
            if (window.ShowDialog() == true)
                {
                UpdateEverything();
                }
            }

        private void ImportDataMenuItem_Click(object sender, RoutedEventArgs e)
            {
            var window = new ImportWindow();
            if (window.ShowDialog() == true)
                {
                UpdateEverything();
                }
            }

        private void ExitMenuItem_Click(object sender, RoutedEventArgs e)
            {
            this.Close();
            }

        private void AddNoticeToPlayListMenuItem_Click(object sender, RoutedEventArgs e)
            {
            var window = new EditNoticeWindow();
            if (window.ShowDialog() == true)
                {
                var listBoxItem = new PlayListItemModel(window.Notice, false);
                ServiceListBox.Items.Add(listBoxItem);
                UpdateEnabledState();
                }
            }

        private void AddBannerToPlayListMenuItem_Click(object sender, RoutedEventArgs e)
            {
            var window = new EditBannerWindow();
            if (window.ShowDialog() == true)
                {
                var listBoxItem = new PlayListItemModel(window.Banner, false);
                ServiceListBox.Items.Add(listBoxItem);
                UpdateEnabledState();
                }
            }

        private void AddVideoToPlayListMenuItem_Click(object sender, RoutedEventArgs e)
            {
            var window = new EditVideoWindow();
            if (window.ShowDialog() == true)
                {
                var listBoxItem = new PlayListItemModel(window.Video, false);
                ServiceListBox.Items.Add(listBoxItem);
                UpdateEnabledState();
                }
            }

        private void AddSongToPlayListMenuItem_Click(object sender, RoutedEventArgs e)
            {
            var window = new SelectSongsWindow();
            if (window.ShowDialog() == true)
                {
                foreach (var song in window.SelectedSongs)
                    {
                    var serviceItem = new SongServiceItem(song, song.DefaultStyle ?? State.Settings.DefaultStyle);
                    var listBoxItem = new PlayListItemModel(serviceItem, false);
                    ServiceListBox.Items.Add(listBoxItem);
                    }
                UpdateEnabledState();
                }
            }

        private void AddBibleChapterToPlayListMenuItem_Click(object sender, RoutedEventArgs e)
            {
            var window = new SelectBibleChaptersWindow();
            if (window.ShowDialog() == true)
                {

                // Add the selected bible chapters
                foreach (var chapter in window.SelectedChapters)
                    {
                    var serviceItem = new BibleServiceItem(chapter, State.Settings.DefaultStyle);
                    var listBoxItem = new PlayListItemModel(serviceItem, false);
                    ServiceListBox.Items.Add(listBoxItem);
                    }
                UpdateEnabledState();

                }
            }

        private void RemoveFromPlayListButton_Click(object sender, RoutedEventArgs e)
            {

            // Ask for confirmation if more than one item is selected
            var ok = true;
            if (ServiceListBox.SelectedItems.Count > 1)
                {
                ok = Utilities.Confirm("Confirm", "You have selected multiple items. Are you sure you want to remove all of those items from the play list?");
                }

            // Remove the items
            if (ok)
                {
                while (ServiceListBox.SelectedItems.Count > 0)
                    {
                    var selectedItem = (PlayListItemModel)ServiceListBox.SelectedItem;
                    ServiceListBox.Items.Remove(selectedItem);

                    // Remove from verses list if the song being removed is active
                    var item = selectedItem.Data;
                    if (item.GetType() == typeof(SongServiceItem) && VersesListBox.ActiveSong == ((SongServiceItem)item).Song)
                        {
                        VersesListBox.ChangeSong(null);
                        }

                    }
                UpdateEnabledState();
                }

            }

        private void SongsListBox_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
            {
            AddSongToPlayListButton_Click(sender, e);
            }

        private void UpdateEverything()
            {

            // Update all controls that may need updating
            UpdateCategoriesList();
            UpdateSongsList();
            UpdateEnabledState();

            // Update the window title
            this.Title = "PowerSong - " + Path.GetFileNameWithoutExtension(State.Database.FileName);

            }

        private void UpdateCategoriesList()
            {
            var categories = State.Database.Categories.GetAllCategories().OrderBy(category => category.Name);
            var items = CheckListBoxItem.CreateItems(categories.ToArray());
            CategoriesListBox.ItemsSource = items;
            }

        private void UpdateSongsList()
            {
            if (SongsListBox != null)
                {
                SongsListBox.Items.Clear();
                var categories = CategoriesListBox.GetCheckedItems();
                var songs = State.Database.Songs.GetAllSongs().OrderBy(song => song.Title);
                foreach (var song in songs)
                    {
                    if (song.Categories.Any(a => categories.Any(b => a.ID == ((Category)b).ID)))
                        {
                        SongsListBox.Items.Add(song);
                        }
                    }
                }
            }

        private void UpdateEnabledState()
            {

            var styleableItemCount = 0;
            foreach (PlayListItemModel selectedItem in ServiceListBox.SelectedItems)
                {
                var item = selectedItem.Data;
                if (item is IStyledServiceItem) styleableItemCount += 1;
                }

            // Determine some information about the current state of the application
            var songSelected = SongsListBox.SelectedItems.Count > 0;
            var serviceItemSelected = ServiceListBox.SelectedItems.Count > 0;
            var verseSelected = VersesListBox.SelectedVerseIndex != -1;
            var canStyleServiceItem = styleableItemCount > 0;

            // Enable or disable various controls
            this.ClearPlayListMenuItem.IsEnabled = ServiceListBox.Items.Count > 0;
            this.CategoriesListBox.IsEnabled = SongsRadioButton.IsChecked == true;
            this.NewSongMenuItem.IsEnabled = SongsRadioButton.IsChecked == true;
            this.AddSongToPlayListButton.IsEnabled = songSelected;
            this.EditSongButton.IsEnabled = State.ActiveSong != null;
            this.ShowEverythingButton.IsEnabled = State.ActiveSong != null;
            this.ShowBackgroundButton.IsEnabled = State.ActiveSong != null;
            this.ActivateSongButton.IsEnabled = serviceItemSelected;
            this.MoveUpButton.IsEnabled = serviceItemSelected && ServiceListBox.Items.Count > 1 && ServiceListBox.SelectedItems.Count == 1;
            this.MoveDownButton.IsEnabled = serviceItemSelected && ServiceListBox.Items.Count > 1 && ServiceListBox.SelectedItems.Count == 1;
            this.NextButton.IsEnabled = State.ActiveSong != null && State.ActiveSong.Verses.Count > 1;
            this.PreviousButton.IsEnabled = State.ActiveSong != null && State.ActiveSong.Verses.Count > 1;
            this.RemoveFromPlayListButton.IsEnabled = serviceItemSelected;
            this.ShowBackgroundMenuItem.IsEnabled = State.ActiveSong != null;
            this.ShowEverythingMenuItem.IsEnabled = State.ActiveSong != null;
            this.EditSongMenuItem.IsEnabled = songSelected && SongsRadioButton.IsChecked == true;
            this.DeleteSongButton.IsEnabled = songSelected && SongsRadioButton.IsChecked == true;
            this.DeleteSongMenuItem.IsEnabled = songSelected && SongsRadioButton.IsChecked == true;
            this.ProjectSongNowMenuItem.IsEnabled = songSelected;
            this.AddSelectedSongToPlayListMenuItem.IsEnabled = songSelected;
            this.ChangeServiceItemOptionsButton.IsEnabled = serviceItemSelected;
            this.ChangeServiceItemOptionsMenuItem.IsEnabled = serviceItemSelected;
            this.ChangeServiceItemStyleButton.IsEnabled = canStyleServiceItem;
            this.ChangeServiceItemStyleMenuItem.IsEnabled = canStyleServiceItem;
            this.ProjectServiceItemNowMenuItem.IsEnabled = serviceItemSelected;
            this.RemoveServiceItemFromPlayListMenuItem.IsEnabled = serviceItemSelected;
            this.ProjectSelectedVerseMenuItem.IsEnabled = verseSelected;
            this.EditSongFromVerseListMenuItem.IsEnabled = VersesListBox.ActiveSong != null;
            this.AddVerseMenuItem.IsEnabled = VersesListBox.ActiveSong != null;
            this.EditVerseMenuItem.IsEnabled = verseSelected;
            this.DeleteVerseMenuItem.IsEnabled = verseSelected;
            this.BibleRadioButton.IsEnabled = State.Bible != null;
            this.MoveDownButton.IsEnabled = ServiceListBox.SelectedItems.Count == 1 && ServiceListBox.SelectedIndex < ServiceListBox.Items.Count - 1;
            this.MoveUpButton.IsEnabled = ServiceListBox.SelectedItems.Count == 1 && ServiceListBox.SelectedIndex > 0;
            this.AddSongButton.IsEnabled = SongsRadioButton.IsChecked == true;

            }

        private void CreateDatabaseMenuItem_Click(object sender, RoutedEventArgs e)
            {
            if (WelcomeWindow.CreateDatabase()) UpdateEverything();
            }

        private void LoadDatabaseMenuItem_Click(object sender, RoutedEventArgs e)
            {
            if (WelcomeWindow.LoadDatabase())
                {
                UpdateEverything();
                Utilities.ShowInformationMessage("Database Loaded", "The selected PowerSong database has been loaded.");
                }
            }

        private void ReportingMenuItem_Click(object sender, RoutedEventArgs e)
            {
            new ReportWindow().ShowDialog();
            }

        private void AddSongToPlayListButton_Click(object sender, RoutedEventArgs e)
            {
            foreach (Song song in SongsListBox.SelectedItems)
                {
                ServiceItem serviceItem = null;
                if (SongsRadioButton.IsChecked == true)
                    {
                    serviceItem = new SongServiceItem(song, song.DefaultStyle ?? State.Settings.DefaultStyle);
                    }
                else
                    {
                    serviceItem = new BibleServiceItem(song, State.Settings.DefaultStyle);
                    }
                var listBoxItem = new PlayListItemModel(serviceItem, false);
                ServiceListBox.Items.Add(listBoxItem);
                UpdateEnabledState();
                }
            }

        private void ActivateSongButton_Click(object sender, RoutedEventArgs e)
            {

            // Get the currently selected service item
            var selectedItem = (PlayListItemModel)ServiceListBox.SelectedItem;
            var selectedServiceItem = selectedItem.Data;
            if (selectedServiceItem != null)
                {

                // Get the title, lyrics (etc) of the item being switched to
                Song song = null;
                if (selectedServiceItem is SongServiceItem) song = ((SongServiceItem)selectedServiceItem).Song;
                if (selectedServiceItem is NoticeServiceItem) song = ((NoticeServiceItem)selectedServiceItem).Notice;
                if (selectedServiceItem is BibleServiceItem) song = ((BibleServiceItem)selectedServiceItem).Chapter;

                // Are we deactivating a song, and need to report it?
                bool hidingSong = State.ActiveSong != null && song != State.ActiveSong && State.Database.Songs.Contains(State.ActiveSong);
                if (hidingSong && State.Settings.EnableReporting)
                    {
                    State.Database.ActivityLog.Write(ActivityItemType.Song, State.ActiveSong.ID, ActivityAction.Hidden);
                    }

                // Set the active item in the list box to be this item
                foreach (PlayListItemModel item in ServiceListBox.Items)
                    {
                    item.IsActive = false;
                    }
                selectedItem.IsActive = true;

                // Perform processing depending on what we are changing to
                if (selectedServiceItem is SongServiceItem || selectedServiceItem is NoticeServiceItem || selectedServiceItem is BibleServiceItem)
                    {

                    // If this is a song in the database, then record that we are showing it
                    if (State.Settings.EnableReporting && State.Database.Songs.Contains(song))
                        {
                        State.Database.ActivityLog.Write(ActivityItemType.Song, song.ID, ActivityAction.Shown);
                        }

                    // Change to verse mode
                    VersesGrid.Visibility = Visibility.Visible;
                    VideoGrid.Visibility = Visibility.Collapsed;

                    // Change the song
                    State.ChangeSong(song);
                    State.Theatre.ChangeText(song.Title, song.Verses.ToArray(), song.Copyright);

                    // Change the style
                    if (selectedServiceItem is IStyledServiceItem)
                        {
                        State.Theatre.SetStyle((IStyledServiceItem)selectedServiceItem);
                        }                    

                    // Show verses in verse list box
                    VersesListBox.ChangeSong(song);

                    }
                else if (selectedServiceItem is VideoServiceItem)
                    {

                    // Change to video mode
                    VersesGrid.Visibility = Visibility.Collapsed;
                    VideoGrid.Visibility = Visibility.Visible;

                    // Change the video
                    var video = (VideoServiceItem)selectedServiceItem;

                    // Show video in video panel
                    VideoPanel.ChangeVideo(video);

                    }
                UpdateEnabledState();
                }

            }

        private void ServiceListBox_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
            {
            ActivateSongButton_Click(sender, e);
            }

        private void SongsListBox_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
            {
            UpdateEnabledState();
            }

        private void ServiceListBox_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
            {
            UpdateEnabledState();
            }

        private void ConfigureLicensesMenuItem_Click(object sender, RoutedEventArgs e)
            {
            new EditLicensesWindow().ShowDialog();
            }

        private void LoadPlayListMenuItem_Click(object sender, RoutedEventArgs e)
            {

            // Get the file name of the play list
            var fileName = OpenFileControl.RequestFileName(FileFilters.PlayList);
            if (!string.IsNullOrEmpty(fileName))
                {

                // If necessary, ask the user whether or not they would like to append songs to the end of the play list
                var clear = false;
                if (ServiceListBox.Items.Count > 0)
                    {
                    clear = Utilities.Confirm("Load Play List",
                                              "Do you wish to clear the play list before loading the file?" + Environment.NewLine + Environment.NewLine +
                                              "Select no if you wish to load the list and have everything appended to the end of the current list.");
                    }

                // Clear the play list if necessary
                if (clear) ServiceListBox.Items.Clear();

                // Load the play list
                var messages = new List<string>();
                var playList = PlayList.Load(State.Database, fileName, messages);
                for (var itemIndex = 0; itemIndex < playList.Count(); itemIndex++)
                    {
                    var listBoxItem = new PlayListItemModel(playList[itemIndex], false);
                    ServiceListBox.Items.Add(listBoxItem);
                    }

                // Display any messages
                if (messages.Count > 0)
                    {
                    MessagesWindow.Show("The following issues were encountered loading the play list. Please review these messages before continuing.", messages.ToArray());
                    }

                // Update enabled state
                UpdateEnabledState();

                }
            }

        private void SavePlayListMenuItem_Click(object sender, RoutedEventArgs e)
            {
            var fileName = SaveFileControl.RequestFileName(FileFilters.PlayList);
            if (!string.IsNullOrEmpty(fileName))
                {
                var playList = new PlayList();
                foreach (PlayListItemModel item in ServiceListBox.Items)
                    {
                    playList.Add(item.Data);
                    }
                playList.Save(fileName);
                }
            }

        private void ClearPlayListMenuItem_Click(object sender, RoutedEventArgs e)
            {
            if (Utilities.Confirm("Clear Play List", "Are you sure you wish to remove all of the items in the play list?"))
                {
                ServiceListBox.Items.Clear();
                VersesListBox.ChangeSong(null);
                UpdateEnabledState();
                }
            }

        private void AddVerseMenuItem_Click(object sender, RoutedEventArgs e)
            {
            var window = new EditVerseWindow();
            if (window.ShowDialog() == true)
                {
                }
            }

        private void EditVerseMenuItem_Click(object sender, RoutedEventArgs e)
            {
            var window = new EditVerseWindow();
            if (window.ShowDialog() == true)
                {
                }
            }

        private void DeleteVerseMenuItem_Click(object sender, RoutedEventArgs e)
            {
            if (Utilities.Confirm("Delete Verse", "Are you sure you wish to permanently delete the selected verse from the currently active song?"))
                {
                }
            }

        private void EditSongMenuItem_Click(object sender, RoutedEventArgs e)
            {
            var song = (Song)SongsListBox.SelectedItem;
            var window = new EditSongWindow(song);
            if (window.ShowDialog() == true)
                {
                UpdateSongsList();
                UpdateCategoriesList();
                UpdateEnabledState();
                }
            }

        private void QueryTextBox_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
            {

            // Remove everything from the list
            SongsListBox.Items.Clear();

            // Are we getting songs?
            if (SongsRadioButton.IsChecked == true)
                {
                PerformSongSearch(QueryTextBox.Text);
                }
            else
                {

                // Search for Bible chapters
                foreach (var chapterName in State.Bible.FindChapters(QueryTextBox.Text))
                    {
                    var verses = State.Bible.FindChapter(chapterName).Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
                    var item = new Song(chapterName, verses);
                    SongsListBox.Items.Add(item);
                    }

                }
            }

        private void PerformSongSearch(string query)
            {

            var candidateSongs = new List<Song>();
            if (!string.IsNullOrWhiteSpace(query))
                {

                // Find songs using the search engine
                var songIDs = State.Searcher.Search(query);
                foreach (var songIdentifier in songIDs)
                    {
                    var song = State.Database.Songs.Get(new Guid(songIdentifier));
                    candidateSongs.Add(song);
                    }

                }
            else
                {

                // Display all songs
                var songs = State.Database.Songs.GetAllSongs();
                foreach (var song in songs)
                    {
                    candidateSongs.Add(song);
                    }

                }

            // Filter candidate songs by the selected categories
            var selectedCategories = new List<Category>();
            foreach (CheckListBoxItem category in CategoriesListBox.Items)
                {
                if (category.IsChecked) selectedCategories.Add((Category)category.Value);
                }
            foreach (var song in candidateSongs)
                {
                foreach (var category in song.Categories)
                    {
                    if (selectedCategories.Contains(category))
                        {
                        SongsListBox.Items.Add(song);
                        break;
                        }
                    }

                }

            }

#warning Check song index is being updated in various scenarios - ie, edit song, add song after import, after edit verse etc

        private void ChangeServiceItemStyleButton_Click(object sender, RoutedEventArgs e)
            {

            // Group items into types
            var selectedItems = new List<IStyledServiceItem>();
            bool selectedNonStyleableItem = false;
            foreach (PlayListItemModel selectedItem in ServiceListBox.SelectedItems)
                {
                var item = selectedItem.Data;
                if (item is IStyledServiceItem)
                    {
                    selectedItems.Add((IStyledServiceItem)item);
                    }
                else
                    {
                    selectedNonStyleableItem = true;
                    }
                }

            // Has the user selected only items that can be styled?
            if (selectedItems.Count > 0 && !selectedNonStyleableItem)
                {

                // Show the window allowing the user to edit the style
                new SelectStyleWindow(selectedItems.ToArray()).ShowDialog();

                // Update the style if one of the items is the currently active item
#warning Implement this

                }
            else
                {

                // The user has confused us!
                Utilities.ShowInformationMessage("Multiple Item Types Selected",
                                                 "You have selected multiple items, however you have also selected at least one item that cannot be styled.",
                                                 "Please select one or more items that can be restyled together, or perhaps work with one item at a time.");

                }

            }

        private void MoveUpButton_Click(object sender, RoutedEventArgs e)
            {
            var selectedIndex = ServiceListBox.SelectedIndex;
            var selectedItem = ServiceListBox.SelectedItem;
            ServiceListBox.Items.Remove(selectedItem);
            ServiceListBox.Items.Insert(selectedIndex - 1, selectedItem);
            ServiceListBox.SelectedItem = selectedItem;
            UpdateEnabledState();
            }

        private void MoveDownButton_Click(object sender, RoutedEventArgs e)
            {
            var selectedIndex = ServiceListBox.SelectedIndex;
            var selectedItem = ServiceListBox.SelectedItem;
            ServiceListBox.Items.Remove(selectedItem);
            ServiceListBox.Items.Insert(selectedIndex + 1, selectedItem);
            ServiceListBox.SelectedItem = selectedItem;
            UpdateEnabledState();
            }

        private void BibleRadioButton_Checked(object sender, RoutedEventArgs e)
            {
            SongsListBox.Items.Clear();
            foreach (var chapterName in State.Bible.GetAllChapters())
                {
                var verses = State.Bible.FindChapter(chapterName).Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
                var item = new Song(chapterName, verses);
                item.Copyright = State.Bible.Translation;
                SongsListBox.Items.Add(item);
                }
            UpdateEnabledState();
            }

        private void SongsRadioButton_Checked(object sender, RoutedEventArgs e)
            {
            UpdateSongsList();
            UpdateEnabledState();
            }

        private void VersesListBox_ActiveVerseChanged(Song song, int verseIndex)
            {
            State.Theatre.ChangeVerse(verseIndex);
            }

        private void PreviousButton_Click(object sender, RoutedEventArgs e)
            {
            if (VersesListBox.ActiveSong.Verses.Count > 1)
                {
                var newVerseIndex = VersesListBox.ActiveVerseIndex - 1;
                if (newVerseIndex < 0) newVerseIndex = VersesListBox.ActiveSong.Verses.Count - 1;
                VersesListBox.ChangeVerse(newVerseIndex);
                }
            }

        private void CategoriesListBox_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
            {
            QueryTextBox_TextChanged(null, null);
            }

        private void CategoriesListBox_CheckedChanged(object item, bool isChecked)
            {
            UpdateSongsList();
            }

        }

    }
